package com.gopay.checkorder.service.task;

import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import org.apache.commons.lang3.time.StopWatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.gopay.checkorder.dao.BisBankOrderQueryDAO;
import com.gopay.checkorder.service.BankOrderService;
import com.gopay.checkorder.service.alarm.OrderAlarmDataCollector;
import com.gopay.checkorder.service.alarm.OrderAlarmRecordStorage;
import com.gopay.checkorder.service.task.thread.CheckOrderThread;
import com.gopay.common.domain.bank.BankOrder;
import com.gopay.common.util.ExecutorUtil;
import com.gopay.common.util.spring.SpringContextUtil;

public class AbcCheckOrderTaskImpl implements Task {

	private final static Logger logger = LoggerFactory
			.getLogger(AbcCheckOrderTaskImpl.class);

	private static final int MAX_THREAD_COUNT = 10;

	private ExecutorService threadPool = Executors
			.newFixedThreadPool(MAX_THREAD_COUNT);

	@Resource(name = "bisBankOrderQueryDAO")
	private BisBankOrderQueryDAO bisBankOrderQueryDAO;

	@Resource(name = "bankOrderService")
	private BankOrderService bankOrderService;

	@Resource(name = "orderAlarmRecordStorage")
	private OrderAlarmRecordStorage orderAlarmRecordStorage;

	private String BANK = "ABC";

	/**
	 * 银行流水状态
	 */
	private String orderStatus;

	/**
	 * 对单次数
	 */
	private int totalCheckTimes;

	private void printLog(StopWatch sw, String bank, String orderStatus,
			int totalCheckTimes, String prefix) {
		sw.split();
		logger.error(prefix + "------,bank=" + BANK + ",orderStatus="
				+ orderStatus + ",totalCheckTimes=" + totalCheckTimes + ",耗时="
				+ sw.getSplitTime());
	}

	/**
	 * 任务执行
	 */
	public void doTask() {
		try {
			StopWatch sw = new StopWatch();
			sw.start();
			printLog(sw, BANK, orderStatus, totalCheckTimes,"AbcCheckOrderTaskImpl------start");

			int pageSize = 300;
			int pageIndex = 1;
			int count = 0;

			checkBefore();

			List<BankOrder> list = getCheckOrder(orderStatus, totalCheckTimes,
					pageIndex, pageSize);
			printLog(sw, BANK, orderStatus, totalCheckTimes,"AbcCheckOrderTaskImpl------list.size()=" + list.size()+ ",pageIndex=" + pageIndex);
			// 订单对账报警采集者
			OrderAlarmDataCollector alarmCollector = new OrderAlarmDataCollector();

			// 订单队列
			ConcurrentLinkedQueue<BankOrder> queue = new ConcurrentLinkedQueue<BankOrder>();
			queue.addAll(list);

			// 同步锁存器
			CountDownLatch latch = new CountDownLatch(queue.size());

			// 线程池中线程全部参与
			for (int i = 0; i < MAX_THREAD_COUNT; i++) {
				CheckOrderThread thread = new CheckOrderThread(bankOrderService, queue, latch, alarmCollector);
				threadPool.execute(thread);

			}

			// 同步锁存器等待所有线程执行完成
			if (!latch.await(118, TimeUnit.SECONDS)) {
				logger.error("同步锁存器等待超时了 latch.count=" + latch.getCount());
				threadPool.awaitTermination(1, TimeUnit.SECONDS);
			}
			// 判断报警阈值并保存报警记录
			orderAlarmRecordStorage.store(alarmCollector);

			printLog(sw, BANK, orderStatus, totalCheckTimes,
					"AbcCheckOrderTaskImpl------end");
			sw.stop();

		} catch (Throwable t) {
			logger.error("执行对单Task时出现异常", t);
		}
	}

	/**
     * 
     */
	private void checkBefore() {
	}

	/**
	 * 待对账订单笔数
	 * 
	 * @param orderStatus
	 * @param totalCheckTimes
	 * @return
	 */
	/*
	 * protected int getCheckOrderCount(String orderStatus){ int resCount =
	 * bisBankOrderQueryDAO.getCheckOrderCountByBank(orderStatus,BANK); if
	 * (resCount > MAX_SIZE) { resCount = MAX_SIZE; } return resCount; }
	 */
	/**
	 * 分页查询对账记录
	 * 
	 * @param orderStatus
	 * @param totalCheckTimes
	 * @param pageIndex
	 * @param pageSize
	 * @return
	 */
	protected List<BankOrder> getCheckOrder(String orderStatus,
			int totalCheckTimes, int pageIndex, int pageSize) {
		/*if ("96".equals(orderStatus)) {
			return bisBankOrderQueryDAO.getCheckOrderByBank(orderStatus,
					pageIndex, pageSize, BANK);
		} else {*/
			return bisBankOrderQueryDAO.getCheckOrderByBank(orderStatus,
					totalCheckTimes, pageIndex, pageSize, BANK);
		/*}*/

	}

	public void setOrderStatus(String orderStatus) {
		this.orderStatus = orderStatus;
	}

	public void setTotalCheckTimes(int totalCheckTimes) {
		this.totalCheckTimes = totalCheckTimes;
	}

}
